package com.feicheng.iou.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.feicheng.iou.constant.ProvideConstant;
import com.feicheng.iou.constant.RepaymentConstant;
import com.feicheng.iou.constant.SessionConstant;
import com.feicheng.iou.entity.*;
import com.feicheng.iou.mapper.*;
import com.feicheng.iou.pojo.PaymentItemPOJO;
import com.feicheng.iou.pojo.ResultPaymentItemPOJO;
import com.feicheng.iou.pojo.ResultPaymentPOJO;
import com.feicheng.iou.pojo.login.LoginReturnPOJO;
import com.feicheng.iou.result.ResultInfoV110;
import com.feicheng.iou.service.PaymentItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feicheng.iou.util.PageUtil;
import com.feicheng.iou.util.CountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author tianchunlei
 * @since 2021-06-28
 */
@Service
@Slf4j
public class PaymentItemServiceImpl extends ServiceImpl<PaymentItemMapper, PaymentItem> implements PaymentItemService {

    @Autowired
    PaymentItemMapper paymentItemMapper;
    @Autowired
    RelMapper relMapper;
    @Autowired
    StudentMapper studentMapper;
    @Autowired
    PaymentRecordMapper paymentRecordMapper;
    @Autowired
    PaymentMapper paymentMapper;


    @Override
    public ResultInfoV110 calculatePaymentItemList(PaymentOptions paymentOptions, BigDecimal amount) {
        log.info("PaymentItemServiceImpl类进去，calculatePaymentItemList方法进入");

        Integer base = paymentOptions.getBase();
        BigDecimal rate = paymentOptions.getRate();
        Integer main = paymentOptions.getMain();


        List<PaymentItem> paymentItemList = new ArrayList<>();
        //得到月服务费率
        BigDecimal bigDecimal = new BigDecimal(100);
        BigDecimal monthRate = rate.divide(bigDecimal, 6, BigDecimal.ROUND_UNNECESSARY);
        //月服务管理费用= 课程总费用 * 月服务费率
        BigDecimal Service = amount.multiply(monthRate);
        //总期数为利息期数和本金期数
        Integer number = base + main;
        //总服务管理费用= 月服务管理费用 * 总月数
        BigDecimal bigDecimalNumber = new BigDecimal(number);
        BigDecimal totalService = Service.multiply(bigDecimalNumber);
        //总金额 = 总服务管理费用 + 课程的总费用
        BigDecimal totalAmount = totalService.add(amount);
        //判断分期是否为零期
        if (number == 0) {
            PaymentItem paymentItem = new PaymentItem();
            paymentItem.setReceivables(amount);
            paymentItem.setPayable(new BigDecimal(0));
            paymentItem.setService(new BigDecimal(0));
            paymentItem.setNumber(0);
            paymentItemList.add(paymentItem);
        } else {
            //每月课程费
            BigDecimal bigDecimalMain = new BigDecimal(main);
            BigDecimal monthClassaMounnt = amount.divide(bigDecimalMain, 6, BigDecimal.ROUND_UP);
            //每月还款费用（不包括前期利息月）=每月服务费+每月课程费
            BigDecimal monthReceivables = Service.add(monthClassaMounnt);
            //循环处理还款记录添加
            for (int i = 0; i < number; i++) {
                PaymentItem paymentItem = new PaymentItem();
                if (base >= i + 1) {
                    paymentItem.setReceivables(new BigDecimal(0));
                    paymentItem.setPayable(Service);
                } else {
                    paymentItem.setPayable(monthReceivables);
                    paymentItem.setReceivables(monthClassaMounnt);
                }
                paymentItem.setService(Service);
                paymentItem.setNumber(i + 1);
                paymentItemList.add(paymentItem);
            }
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("number", number);
        resultMap.put("rate", monthRate);
        resultMap.put("totalService", totalService);
        resultMap.put("paymentItemList", paymentItemList);
        resultMap.put("paymentOptions", paymentOptions);

        log.info("selectProjectServiceList方法结束");
        log.debug("selectProjectServiceList方法返回的map: " + resultMap);
        return ResultInfoV110.success(resultMap);
    }

    @Override
    public ResultInfoV110 selectPaymentItemListByPid(Integer paymenId) {
        log.info("selectPaymentItemList方法进入，参数为" + paymenId);

        /* 传入的放到paymentItemQueryWrapper中，调用mapper查询匹配的数据列表  */
        QueryWrapper<PaymentItem> paymentItemQueryWrapper = new QueryWrapper<>();
        paymentItemQueryWrapper.eq("p_id", paymenId);
        List<PaymentItem> paymentItems = paymentItemMapper.selectList(paymentItemQueryWrapper);

        log.info("selectPaymentItemList方法结束，参数为" + paymenId);
        log.debug("selectPaymentItemList方法返回的list: " + paymentItems);
        return ResultInfoV110.success(paymentItems);
    }

    @Override
    public ResultInfoV110 selectPaymentItemList(PaymentItemPOJO paymentItemPOJO) {
        log.info("selectPaymentItemList方法进去，参数为" + paymentItemPOJO);
        String time = paymentItemPOJO.getTime();
        if (!StrUtil.hasEmpty(time)) {
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();
            if (time.equals("today")) {
                paymentItemPOJO.setStartTime(df.format(LocalDateTime.of(now.toLocalDate(), LocalTime.MIN)));
                paymentItemPOJO.setEndTime(df.format(LocalDateTime.of(now.toLocalDate(), LocalTime.MAX)));
            }
            if (time.equals("thisMonth")) {
                log.info("本月进入");
                LocalDateTime thisMonthFirstDay = now.with(TemporalAdjusters.firstDayOfMonth());
                LocalDateTime thisMonthLastDay = now.with(TemporalAdjusters.lastDayOfMonth());
                paymentItemPOJO.setStartTime(df.format(LocalDateTime.of(thisMonthFirstDay.toLocalDate(), LocalTime.MIN)));
                paymentItemPOJO.setEndTime(df.format(LocalDateTime.of(thisMonthLastDay.toLocalDate(), LocalTime.MAX)));
            }
            if (time.equals("thisWeek")) {
                log.info("本周进入");
                LocalDateTime nowMonday = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(DayOfWeek.MONDAY);
                LocalDateTime nowSunday = LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(DayOfWeek.SUNDAY);
                paymentItemPOJO.setStartTime(df.format(nowMonday));
                paymentItemPOJO.setEndTime(df.format(nowSunday));
            }
            if (time.equals("lastMonth")) {
                LocalDateTime localDateTime = now.minusMonths(1);
                LocalDateTime lastMonthFirstDay = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
                LocalDateTime lastMonthLastDay = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
                paymentItemPOJO.setStartTime(df.format(LocalDateTime.of(lastMonthFirstDay.toLocalDate(), LocalTime.MIN)));
                paymentItemPOJO.setEndTime(df.format(LocalDateTime.of(lastMonthLastDay.toLocalDate(), LocalTime.MAX)));
            }

        }
        //定义一个放返回数据的Map
        Map<String, Object> resultMap = new HashMap<>();

        //获取传入数据中的pege当前页，size每页条数得出当前页起始数据索引
        Integer pageIndex = PageUtil.getPageIndex(paymentItemPOJO.getPage(), paymentItemPOJO.getSize());
        //把数据索引封装到resourcePOJO
        paymentItemPOJO.setPageIndex(pageIndex);
        //调用Mapper中查询条数的方法得出条数封装进resourcePOJO
        paymentItemPOJO.setTotal(paymentItemMapper.queryPaymentItemPayCount(paymentItemPOJO));
        //根据传入的pojo查询，结果封装到resourcePOJOSList
        log.info("数据为" + paymentItemPOJO);
        List<ResultPaymentItemPOJO> paymentItemsPay = paymentItemMapper.queryPaymentItemPay(paymentItemPOJO);
//        List<ResultPaymentItemPOJO> paymentItemsAll = paymentItemMapper.queryPaymentItemAll(paymentItemPOJO);

        //查询不分页数据
        List<ResultPaymentItemPOJO> paymentItemsPayNoPage = paymentItemMapper.queryPaymentItemPayNoPage(paymentItemPOJO);
        List<ResultPaymentItemPOJO> paymentItemsAllNoPage = paymentItemMapper.queryPaymentItemAllNoPage(paymentItemPOJO);
        //获取pageutil里的pageinfo里的数据封装到pageinfo这个map
        Map<String, Integer> pageInfo = PageUtil.getPageInfo(paymentItemPOJO.getPage(), paymentItemPOJO.getSize(), paymentItemPOJO.getTotal());

        //查询所有数据
        List<PaymentItem> allPaymentItems = paymentItemMapper.selectList(null);
        //计算总计
        BigDecimal total = CountUtil.getTotal(allPaymentItems);
        //计算总未收
        BigDecimal allreceivable = CountUtil.getAllreceivable(allPaymentItems);
        //计算总实收
        BigDecimal allpayable = total.subtract(allreceivable);

        //计算条件内应收
        BigDecimal timeReceivable = CountUtil.getTimeReceivable(paymentItemsAllNoPage);
        //计算条件内未收
        BigDecimal uncollected = CountUtil.getUncollected(paymentItemsAllNoPage);
        //计算条件内总计
        BigDecimal timeTotalReceivable = CountUtil.getTimeTotalReceivable(paymentItemsPayNoPage);

        for (ResultPaymentItemPOJO resultPaymentItemPOJO : paymentItemsPay) {
            Integer itemNumber = resultPaymentItemPOJO.getPaymentItem().getNumber();
            String paymentNumber = resultPaymentItemPOJO.getPayment().getNumber();
            resultPaymentItemPOJO.setNumber(itemNumber + "/" + paymentNumber);
        }
        //把pageinnfo这个map封装到resultMap中
        resultMap.put("pageInfo", pageInfo);
        //把resourcePOJOSList这个list封装到resultMap中
        resultMap.put("total", total);
        resultMap.put("allpayable", allpayable);
        resultMap.put("allreceivable", allreceivable);
        resultMap.put("timeReceivable", timeReceivable);
        resultMap.put("uncollected", uncollected);
        resultMap.put("timeTotalReceivable", timeTotalReceivable);
        paymentItemsPay.forEach(System.out::println);
        resultMap.put("list", paymentItemsPay);

        log.info("selectPaymentItemList方法结束");
        //把resultMap封装到ResultInfo中
        return ResultInfoV110.success(resultMap);
    }

    @Override
    public ResultInfoV110 confirmPayment(Integer id, HttpServletRequest request) {
        log.info("PaymentItemServiceImpl类进去，selectPaymentItemList方法进入");
        LoginReturnPOJO attribute = (LoginReturnPOJO) request.getSession().getAttribute(SessionConstant.CURRENT);
        Integer userId = attribute.getUser().getUserId();
        String nickName = attribute.getUser().getNickName();
        System.out.println(attribute.getUser());
        PaymentItem paymentItem = new PaymentItem();
        paymentItem.setId(id);
        paymentItem.setConfirmUserId(userId);
        paymentItem.setConfirmUserName(nickName);
        paymentItem.setStatus(RepaymentConstant.YIQUEREN);
        paymentItemMapper.updateById(paymentItem);

        //  修改panment状态为还款中
        Integer pId = paymentItemMapper.selectById(id).getPid();
        Integer number = paymentItemMapper.selectById(id).getNumber();
        Payment paymentInfo = paymentMapper.selectById(pId);
        String totalNumber = paymentInfo.getNumber();
        Integer integer = Integer.valueOf(totalNumber);


        //状态判断，如果是最后一期还款确认，状态则为已结清
        Payment payment = new Payment();
        payment.setId(pId);
        if (integer == number) {
            payment.setStatus(ProvideConstant.YIJIEQING);
        } else {
            payment.setStatus(ProvideConstant.HUANKUANZHONG);
        }
        paymentMapper.updateById(payment);

        QueryWrapper<Rel> wrapper = new QueryWrapper<>();
        wrapper.eq("payment_id", pId);
        Rel rel = relMapper.selectOne(wrapper);
        Integer studentId = rel.getStudentId();
        Student student = studentMapper.selectById(studentId);
        String name = student.getName();


        PaymentRecord paymentRecord = new PaymentRecord();
        paymentRecord.setPId(pId);
        paymentRecord.setConfirmUserName(nickName);
        paymentRecord.setConfirmStatus("学生" + name + "第" + number + "期还款确认");
        LocalDateTime now = LocalDateTime.now();
        paymentRecord.setComfirmTime(now);
        paymentRecord.setStatus(true);
        paymentRecord.setCu(userId);
        paymentRecord.setUu(userId);
        paymentRecordMapper.insert(paymentRecord);
        return ResultInfoV110.success();
    }

    @Override
    public ResultInfoV110 countUnpaid() {
        log.info("PaymentItemServiceImpl类进去，countUnpaid方法进入，参数为");
        HashMap<String, Object> resultMap = new HashMap<>();
        QueryWrapper<PaymentItem> paymentItemQueryWrapper = new QueryWrapper<>();
        paymentItemQueryWrapper.eq("status", RepaymentConstant.YUQIWEIHUAN);
        Integer selectCount = paymentItemMapper.selectCount(paymentItemQueryWrapper);
        resultMap.put("count", selectCount);
        return ResultInfoV110.success(resultMap);
    }

    @Override
    public ResultInfoV110 selectUnpaid() {
        log.info("PaymentItemServiceImpl类进去，countUnpaid方法进入");
        List<ResultPaymentItemPOJO> resultPaymentItemPOJOS = paymentItemMapper.yuqiweifuPaymentItem();
        for (ResultPaymentItemPOJO resultPaymentItemPOJO : resultPaymentItemPOJOS) {
            Integer itemNumber = resultPaymentItemPOJO.getPaymentItem().getNumber();
            String paymentNumber = resultPaymentItemPOJO.getPayment().getNumber();
            resultPaymentItemPOJO.setNumber(itemNumber + "/" + paymentNumber);
        }
        log.info("PaymentItemServiceImpl类进去，countUnpaid方法进入");
        return ResultInfoV110.success(resultPaymentItemPOJOS);
    }

    @Override
    public ResultInfoV110 checkOverdue() {
        QueryWrapper<PaymentItem> paymentItemQueryWrapper = new QueryWrapper<>();
        paymentItemQueryWrapper.eq("status", RepaymentConstant.DAIHUANKUAN);
        List<PaymentItem> paymentItems = paymentItemMapper.selectList(paymentItemQueryWrapper);
        for (PaymentItem paymentItem : paymentItems) {
            LocalDateTime now = LocalDateTime.now();
            Integer paymentItemId = paymentItem.getId();
            LocalDateTime planPayDate = paymentItem.getPlanPayDate();
            if (now.isAfter(planPayDate)) {
                UpdateWrapper<PaymentItem> paymentItemUpdateWrapper = new UpdateWrapper<>();
                paymentItemUpdateWrapper.eq("id", paymentItemId).set("status", RepaymentConstant.YUQIWEIHUAN);
                paymentItemMapper.update(null, paymentItemUpdateWrapper);
            }
        }
        return ResultInfoV110.success();
    }

    @Override
    public ResultInfoV110 countReviewed() {
        log.info("PaymentItemServiceImpl类进去，countReviewed方法进入，参数为");
        HashMap<String, Object> resultMap = new HashMap<>();
        QueryWrapper<PaymentItem> paymentItemQueryWrapper = new QueryWrapper<>();
        paymentItemQueryWrapper.eq("status", RepaymentConstant.YIHUANKUAN);
        Integer selectCount = paymentItemMapper.selectCount(paymentItemQueryWrapper);
        resultMap.put("count", selectCount);
        return ResultInfoV110.success(resultMap);
    }

    @Override
    public ResultInfoV110 selectReviewed() {
        List<ResultPaymentItemPOJO> resultPaymentItemPOJOS = paymentItemMapper.yihuankuanPaymentItem();
        for (ResultPaymentItemPOJO resultPaymentItemPOJO : resultPaymentItemPOJOS) {
            Integer itemNumber = resultPaymentItemPOJO.getPaymentItem().getNumber();
            String paymentNumber = resultPaymentItemPOJO.getPayment().getNumber();
            resultPaymentItemPOJO.setNumber(itemNumber + "/" + paymentNumber);
        }
        log.info("PaymentItemServiceImpl类进去，countUnpaid方法进入");
        return ResultInfoV110.success(resultPaymentItemPOJOS);
    }

    @Override
    public ResultInfoV110 repayment(Integer id, String payMethod, HttpServletRequest request) {

        LoginReturnPOJO attribute = (LoginReturnPOJO) request.getSession().getAttribute(SessionConstant.CURRENT);
        Integer userId = attribute.getUser().getUserId();
        String nickName = attribute.getUser().getNickName();

        PaymentItem paymentItem = new PaymentItem();
        paymentItem.setPayMethod(payMethod)
                .setPayDate(LocalDateTime.now())
                .setId(id);
        paymentItemMapper.updateById(paymentItem);
        this.confirmPayment(id,request);

        return ResultInfoV110.success();
    }

}
